package com.czy.fx.flake;

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Pos;
import javafx.geometry.VPos;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;

import java.util.ArrayList;
import java.util.Random;

/********************************************************************
 * @brief 雪花飘落
 * @version 0.1
 * @date 2024年12月29日 下午9:49
 * @author czy
 ********************************************************************/
public class FlakeMain extends Application {

    private AnchorPane root;
    private Text text;
    private int flakeNum = 1600;
    private Random random = new Random();
    private static final ArrayList<Flake> flakes = new ArrayList<>(2000);

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        root = new AnchorPane();
        text = new Text("FPS: 0");
        text.setFill(Color.WHITE);
        text.setFont(Font.font(30));
        text.setTextOrigin(VPos.TOP);
        root.getChildren().add(text);
        Scene scene = new Scene(root, 1000, 1000);
        String bgUrl = getClass().getResource("/flake/bj.png").toExternalForm();
        root.setStyle("-fx-background-image: url('" + bgUrl + "');" + "-fx-background-size: cover;");
        root.prefWidthProperty().bind(scene.widthProperty());
        root.prefHeightProperty().bind(scene.heightProperty());
        primaryStage.setScene(scene);
        primaryStage.setTitle("雪花飘落");
        primaryStage.show();
        initShow();
        //帧率动画，1s大概60次刷新频率
        AnimationTimer timer = new AnimationTimer() {

            int times = 0;
            boolean direction = false;
            Long LAST_TIME = System.nanoTime();
            double duration;
            //1秒=10亿纳秒
            Long ONE_SECOND = 1_000_000_000L;
            int fps;

            @Override
            public void handle(long now) {
                fps++;
                duration += now - LAST_TIME;
                if (duration >= ONE_SECOND) {
                    text.setText("FPS: " + fps);
                    duration -= ONE_SECOND;
                    fps = 0;
                }
                LAST_TIME = now;
                times++;
                if (times % 180 == 0) {
                    // 1秒60次调用，%180就是3秒变一次水平移动方向
                    direction = true;
                    times = 0;
                }
                //每帧进行雪花移动
                flakes.forEach((flake) -> {
                    //雪花旋转效果
                    flake.setRotate((flake.getRotate()+3)%360);
                    //雪花落地透明效果，越往下越透明
                    flake.setOpacity(1 - flake.getY() / root.getPrefHeight());
                    flake.setY(flake.getY() + flake.getvSpeed());
                    if (direction) {
                        flake.sethSpeed(-flake.gethSpeed());
                    }
                    flake.setX(flake.getX() + flake.gethSpeed());
                    if (flake.getY() > root.getPrefHeight()) {
                        flake.setX(random.nextDouble() * root.getPrefWidth());
                        flake.setY(0);
                        flake.setRotate(random.nextDouble()*360);
                        flake.setvSpeed(random.nextDouble() *2.5+0.5);
                        flake.sethSpeed(random.nextDouble() - 0.5);

                    }

                });
                direction = false;
            }
        };
        timer.start();

    }

    private void initShow() {
        for (int i = 0; i < flakeNum; i++) {
            Flake flake = new Flake(random.nextInt(2));
            flake.setX(random.nextDouble() * root.getPrefWidth());
            flake.setY(random.nextDouble() * root.getPrefHeight());
            flake.setRotate(random.nextDouble()*360);
            flake.setOpacity(1 - flake.getY() / root.getPrefHeight());
            //0~2
            flake.setvSpeed(random.nextDouble() *2.5+0.5);
            //-1~1
            flake.sethSpeed(random.nextDouble()- 0.5);
            flakes.add(flake);
        }
        root.getChildren().addAll(flakes);

    }
}
